
package astexec

import (
  "asteval"
  "environ"
  "math/big"
  "os"
  "bufio"
  "container/list"
)

type Statement interface {
  Execute(env *environ.Environment)
}

type Sequence struct {
  children *list.List
}

func NewSequence() *Sequence {
  return &Sequence{children: list.New().Init()}
}

func (q *Sequence) Append(st Statement) {
  q.children.PushBack(st)
}

func (q *Sequence) Execute(env *environ.Environment) {
  for e := q.children.Front(); e != nil; e = e.Next() {
    st := e.Value.(Statement)
    st.Execute(env)
  }
}

type Assignment struct {
  name string
  expr *asteval.Expression
}

func NewAssignment(nm string, ex *asteval.Expression) *Assignment {
  return &Assignment{name: nm, expr: ex}
}

func (a *Assignment) Execute(env *environ.Environment) {
  val := a.expr.Evaluate(env)
  env.Set(a.name, val)
}

type Input struct {
  name string
}

func NewInput(nm string) *Input {
  return &Input{name: nm}
}

func (i *Input) Execute(env *environ.Environment) {
  reader := bufio.NewReader(os.Stdin)
  num, _ := reader.ReadString('\n')
  value := new(big.Int)
  value.SetString(num, 10)
  env.Set(i.name, value)
}

type Print struct {
  expr *asteval.Expression
}

func NewPrint(ex *asteval.Expression) *Print {
  return &Print{expr: ex}
}

func (p *Print) Execute(env *environ.Environment) {
  val := p.expr.Evaluate(env)
  writer := bufio.NewWriter(os.Stdout)
  writer.WriteString(val.String())
  writer.WriteString("\n")
  writer.Flush()
}


